<?php
/**
*
*   TODO getCurrentDate, compare: compare(date1,date2=current) <=> 0

*/

class Yz_Date
    extends Yz_Object
{

    protected static $DATE_FORMATS = array(
        0 => '%{monthNameAndDay} %{year}',
        1 => '%{monthAndDay} %{year}',
        2 => '%{year}.%{month}.%{day}',
    );

    protected $date;

    /*************************
     *      Public methods   *
     *************************/


    /**
     *   @param mixed value
     */
    public function __construct( $y=null, $m=null, $d=null )
    {
        $this->date = $y
            ? $this->valueOf($y)
            : new DateTime()
        ;
    } // __construct


    public function __toString()
    {
        return $this->date->format('Y-m-d');
    }

    public function toArray()
    {
        return explode('-', $this->date->format('Y-m-d'));
    }



    /**
    *   @param scalar | array(3)[y,m,d]
    *   @accept:
    *       - string YY[YY]-MM-DD
    *       - string DD.MM.YY[YY]
    *       - string ????MMDD
    *       - integer MMDD ( 101 : 1231 )
    *       - integer YYMMDD ( YY0101 : 1231, YY is 20YY )
    *       - integer YYYYMMDD ( 10000101 : 99991231 )
    *       - integer UNIX_TIMESTAMP ( 99991232 .... )
    *   @return DateTime
    */
    public static function valueOf( $value )
    {
        switch ( true ) {
            case $value instanceof DateTime:
                $ovalue = $value;
            case $value instanceof Yz_Date:
                $ovalue = $value->date;
                break;
            case is_string( $value ):
                $ovalue = static::parseString($value);
                break;
            case is_int( $value ):
                $ovalue = static::parseTimestamp($value);
                break;
            default:
                $ovalue = null;
        }
        return $ovalue;
    } // valueOf


    /**
     *
     */
    public static function getElapsedTime()
    {
        return  microtime(true) - YZ_TIME;
    } // getElapsedTime


    /** The getter, must be present in order not to throw AttributeError
     *  @return int|null
     */
    public function getDay()   { return (int)$this->date->format('d'); }
    public function getMonth() { return (int)$this->date->format('m'); }
    public function getYear()  { return (int)$this->date->format('Y'); }

    /** Setter for year
     *  Setting year to null substitutes current year
     */
    public function setYear($year)
    {
        $year = Yz_Int::test($year);
        list($y,$m,$d) = explode('-', $this->date->format('Y-m-d'));
        try {
            $this->date->setDate($year, $m, $d);
        } catch (Exception $ex) {
            throw new Yz_Exception_DateError;
        }
        $my['year'] = $year;
        return $this;
    }

    /**
     *
     */
    public function setMonth($month)
    {
        $month = Yz_Int::test($month);
        list($y,$m,$d) = explode('-', $this->date->format('Y-m-d'));
        try {
            $this->date->setDate($y, $month, $d);
        } catch (Exception $ex) {
            throw new Yz_Exception_DateError;
        }
        return $this;
    }

    /**
     *
     */
    public function setDay($day)
    {
        $day = Yz_Int::test($day);
        list($y,$m,$d) = explode('-', $this->date->format('Y-m-d'));
        try {
            $this->date->setDate($y, $m, $day);
        } catch (Exception $ex) {
            throw new Yz_Exception_DateError;
        }
        return $this;
    }

    public function getMonthName()
    {
        return $this->date->format('M');
    }

    public function getTimestamp()
    {
        return $this->date->getTimestamp();
    }


    /**
     *  422, 0422 => Apr 22, this year
     *  22   => 22nd this month this year
     *
     *  @return array[0: year, 1: month, 2: day]|null
     */
    protected static function parseString($value)
    {
        try {
            $v = new DateTime($value);
        } catch (Exception $ex) {
            $v = null;
        }
        return $v;
    }

    /**
     *
     *  @return array[0: year, 1: month, 2: day]|null
     */
    protected static function parseArray($array)
    {
        debug();
        $val = Yz_Array::valueOf($array);
        if (null !== $val && 3 === count($val)) {
            if (checkdate($val[1], $val[2], $val[0])) {
                return $val;
            }
        }
        return null;
    }

    /**
     *
     *  @return array[0: year, 1: month, 2: day]|null
     */
    protected static function parseTimestamp($time)
    {
        debug();
        try {
            $v = new DateTime();
            $v->setTimestamp($time);
        } catch (Exception $ex) {
            $v = null;
        }
        return $v;
    }

} // class Yz_Date

